package com.yonyou.cyxdms.basedata.service.service.basedata;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yonyou.cyx.framework.bean.dto.base.ClientInfoDTO;
import com.yonyou.cyx.framework.compent.redis.RedisClient;
import com.yonyou.cyx.framework.util.bean.ApplicationContextHelper;
import com.yonyou.cyx.function.utils.bean.BeanMapperUtil;
import com.yonyou.cyx.function.utils.common.CommonUtils;
import com.yonyou.cyx.function.utils.common.StringUtils;
import com.yonyou.cyx.function.utils.jsonserializer.JSONUtil;
import com.yonyou.cyxdms.basedata.client.constants.BaseDataCommonConstants;
import com.yonyou.cyxdms.basedata.client.constants.BaseDataDictConstants;
import com.yonyou.cyxdms.basedata.client.domains.vo.DictVO;
import com.yonyou.cyxdms.basedata.client.domains.vo.RegionVO;
import com.yonyou.cyxdms.basedata.client.service.basedata.BaseCommonRegionService;
import com.yonyou.cyxdms.basedata.service.entity.code.CodePO;
import com.yonyou.cyxdms.basedata.service.repository.code.CodeMapper;
import com.yonyou.cyxdms.basedata.service.service.code.CodeService;
import com.yonyou.cyxdms.basedata.service.service.region.RegionService;
import com.yonyou.cyxdms.framework.bean.dto.user_info.LoginInfoDto;
import com.yonyou.cyxdms.framework.constants.FrameworkDictCodeConstants;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * @author     ：quankk
 * @date       ：2019/7/9 15:46
 * @description：
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class DictServiceImpl implements DictService {

    // 定义日志接口
    private static final Logger logger = LoggerFactory.getLogger(DictServiceImpl.class);


    @Autowired
    public BaseCommonRegionService baseCommonRegionService;

    @Autowired
    private CodeService codeService;

    @Autowired
    private RegionService regionService;

    @Autowired
    private RedisClient redisClient;

    @Autowired
    CodeMapper codeMapper;

    /**
     * @author     ：quankk
     * @date       ：2019/7/9 18:04
     * @description：
     */
    //===========   CMS 删除缓存，解决区域查询混乱问题     开始    =======================
//    @Cacheable(value = Constanst.KEY_DICT, key = "'all'", unless = "#result==null")
    //===========   CMS 删除缓存，解决区域查询混乱问题     结束    =======================
    @Override
    public Map<String, Object> queryDicts(String appId) {
        logger.info("查询tc_code和省市开始。。。。。。。。。。。。。。");
        Map<String, Object> dict = new HashMap<>();

        // 定义缓存对象--身份
        Map<Long, RegionVO> regionCacheMap   = new HashMap<>();
        // 城市信息
        Map<Long, RegionVO> cityMap    = new HashMap<>();
        // 区县
        Map<Long, RegionVO> countryMap = new HashMap<>();
        // 街道
        Map<Long, RegionVO> streetMap  = new HashMap<>();

//        LambdaQueryWrapper<RegionPO> queryWrapper = new QueryWrapper().lambda();
//        queryWrapper.orderByAsc(RegionPO :: getRegionType).orderByAsc(RegionPO :: getRegionId);
//        List<RegionPO> regionPOList = regionMapper.selectList(queryWrapper);

//        LambdaQueryWrapper<RegionVO> queryWrapper = new QueryWrapper().lambda();
//        queryWrapper.orderByAsc(RegionVO :: getRegionType).orderByAsc(RegionVO :: getRegionId);
//        List<RegionVO> regionPOList = baseCommonRegionService.listAllData();
        List<RegionVO> regionPoList = listAllData(appId);
        if (CollectionUtils.isNotEmpty(regionPoList)) {
            regionPoList.stream().forEach(regionPo -> {
                Integer type = regionPo.getRegionType();
                RegionVO regionDto = new RegionVO();
                regionDto.setRegionId(regionPo.getRegionId());
                regionDto.setRegionName(regionPo.getRegionName());
                regionDto.setRegionType(regionPo.getRegionType());
                Long parentId = !StringUtils.isNullOrEmpty(regionPo.getParentRegionId()) ? regionPo.getParentRegionId().longValue() : null;

                if (FrameworkDictCodeConstants.REGION_TYPE_PROVINCE == type) {
                    regionDto.setChildren(new HashMap<Long, RegionVO>());
                    regionCacheMap.put(regionDto.getRegionId(), regionDto);
                }

                if (FrameworkDictCodeConstants.REGION_TYPE_CITY == type) {
                    RegionVO parentDto = null;
                    parentDto = regionCacheMap.get(parentId);
                    regionDto.setChildren(new HashMap<Long, RegionVO>());
                    cityMap.put(regionDto.getRegionId(), regionDto);
                    parentDto.getChildren().put(regionDto.getRegionId(), regionDto);
                }

                if (FrameworkDictCodeConstants.REGION_TYPE_COUNTY == type) {
                    RegionVO parentDto = cityMap.get(parentId);
                    regionDto.setChildren(new HashMap<Long, RegionVO>());
                    countryMap.put(regionDto.getRegionId(), regionDto);
                    parentDto.getChildren().put(regionDto.getRegionId(), regionDto);
                }
                // 街道
                if (10001004 == type) {
                    RegionVO parentDto = countryMap.get(parentId);
                    parentDto.getChildren().put(regionDto.getRegionId(), regionDto);
                    streetMap.put(regionDto.getRegionId(), regionDto);
                }
            });
        }

        List<DictVO> dictList = allCodeAvailable(appId);
        Map<Integer,List<DictVO>> cacheMap = new HashMap<>();
        dictList.stream().forEach(dictVO->{
            Integer type = dictVO.getType();
            List<DictVO> listData = null;
            if(cacheMap.get(type)!=null){
                listData = cacheMap.get(type);
            }else{
                listData = new ArrayList<>();
                cacheMap.put(type, listData);
            }
            listData.add(dictVO);
        });

        dict.put("dict", cacheMap);
        dict.put("region", regionCacheMap);
        return dict;
    }


    /**
     * 查询所有省市区数据
     *
     * @param
     * @return java.util.List<com.yonyou.cyxdms.basedata.client.domains.vo.RegionVO>
     * @author dengqiang
     * @since 2019/8/21
     */
    public List<RegionVO> listAllData(String appId) {
        String messageFormat = MessageFormat.format(BaseDataCommonConstants.REGION_CACHE_REGION, appId);
        Object regionDto = redisClient.get(messageFormat);
        if (null == regionDto) {
            // 查询所有数据
            loadValueIfNotExists(messageFormat);
            Object redisregionDto = redisClient.get(messageFormat);
            if (null == redisregionDto) {
                return null;
            }
            return JSONUtil.jsonToList(JSONUtil.objectToJson(redisregionDto), RegionVO.class);
        } else {
            return JSONUtil.jsonToList(JSONUtil.objectToJson(regionDto), RegionVO.class);
        }
    }

    /**
     * 查询数据
     *
     * @param
     * @return void
     * @author dengqiang
     * @since 2019/8/21
     */
    private void loadValueIfNotExists(String message) {
        List<RegionVO> regionResponse = regionService.listAllData();
        logger.info("feign查询region信息:{}", regionResponse);

        if (!CommonUtils.isNullOrEmpty(regionResponse)) {
            initOneValue(regionResponse, message);
        }
    }

    /**
     * 将数据放置redis
     *
     * @param regionList
     * @return void
     * @author dengqiang
     * @since 2019/8/21
     */
    private void initOneValue(List<RegionVO> regionList, String message) {
        redisClient.set(message, JSONUtil.objectToJson(regionList), BaseDataCommonConstants.EXPIRE_TIME_ONE_DAY);
    }

    public List<DictVO> allCodeAvailable(String appId) {
        String messageFormat = MessageFormat.format(BaseDataCommonConstants.ALLCODE_AVAI_CACHE_TYPE, appId);
        Object codeData = redisClient.get(messageFormat);
        if (null == codeData) {
            LambdaQueryWrapper<CodePO> codeParam = new QueryWrapper<CodePO>().lambda();
            codeParam.eq(CodePO::getAppId, appId).eq(CodePO::getIsDeleted, 0)
                    .eq(CodePO::getStatus, BaseDataDictConstants.IS_ON)
                    .orderByAsc(CodePO::getType, CodePO::getNum);
            List<CodePO> codeList = codeMapper.selectList(codeParam);

            List<DictVO> dictVOList = BeanMapperUtil.copyList(codeList, DictVO.class);
            redisClient.set(messageFormat, JSONUtil.objectToJson(dictVOList), BaseDataCommonConstants.EXPIRE_TIME_ONE_DAY);
            return dictVOList;
        }
        return JSONUtil.jsonToList(JSONUtil.objectToJson(codeData), DictVO.class);
    }
}
